﻿using AutoMapper;
using ManagementApi.Services.ProjectImport;
using Modules.Constructor;
using Modules.Corp;
using Modules.Project;
using Modules.Project.Entitys;
using Modules.System.Area;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Exceptions;
using System.Data;
using static Modules.Project.ProjectConstants;

namespace ManagementApi.Services.Import
{
    /// <summary>
    /// 项目基本信息导入
    /// </summary>
    [UseDI(ServiceLifetime.Scoped)]
    public class ProjectImportService
    {
        private readonly IMapper mapper;
        private readonly ProjectService projectService;
        private readonly CorpService corpService;
        private readonly ConstructorService constructorService;
        private readonly AreaService areaService;
        private readonly IApplicationContext applicationContext;
        private readonly ILogger logger;

        /// <summary>
        /// </summary>
        /// <param name="mapper"></param>
        /// <param name="projectService"></param>
        /// <param name="constructorService"></param>
        /// <param name="corpService"></param>
        /// <param name="areaService"></param>
        public ProjectImportService(IMapper mapper, ProjectService projectService, ConstructorService constructorService, CorpService corpService, AreaService areaService, IApplicationContext applicationContext, ILogger<ProjectImportService> logger)
        {
            this.mapper = mapper;
            this.projectService = projectService;
            this.constructorService = constructorService;
            this.corpService = corpService;
            this.areaService = areaService;
            this.applicationContext = applicationContext;
            this.logger = logger;
        }

        /// <summary>
        /// 验证项目基本信息Excel并且转换成集合
        /// </summary>
        /// <param name="file">文件</param>
        /// <returns></returns>
        /// <exception cref="BusinessException"></exception>
        public IEnumerable<ProjectImportDto> VerifyProjectExcelToList(IFormFile file)
        {
            var data = ImportExcelUtil<ProjectImportForm>.InputExcel(file);
            if (data == null || data.Count == 0)
                throw new BusinessException("数据格式解析错误，请上传正确的Excel");

            List<ProjectImportDto> dtos = new();
            var projects = projectService.GetProjectInfosByBiddingSectionNum(data.Select(i => i.BiddingSectionNum));
            var corps = corpService.GetCorpInfos(data.Select(i => i.LumpContractorCorpCode));
            var constructors = constructorService.GetConstructorInfosByName(data.Select(i => i.BuildCorpName));
            var allarea = areaService.GetAllAreas();
            foreach (var item in data)
            {
                ProjectImportDto dto = new ProjectImportDto();
                mapper.Map(item, dto);
                dto.FieldImportLevel = new Dictionary<string, string>();
                dto.FieldImportMsg = new Dictionary<string, string>();
                dto.Status = true;
                dto.ErrorMsg = string.Empty;
                dto.ErrorCount = 0;
                var props = typeof(ProjectImportForm).GetProperties();
                var corp = corps.Where(i => i.Code == item.LumpContractorCorpCode).FirstOrDefault();
                var project = projects.Where(i => i.BiddingSectionNum == item.BiddingSectionNum).FirstOrDefault();
                var constructor = constructors.Where(i => i.Name == item.BuildCorpName).FirstOrDefault();
                foreach (var prop in props)
                {
                    var (Level, Msg) = VerifyProjectField(prop.Name, item, corp, constructor, project, allarea);
                    dto.FieldImportLevel.Add(prop.Name, Level.GetDescription());
                    dto.FieldImportMsg.Add(prop.Name, Msg);
                    if (Level == FieldImportLevel.Danger)
                    {
                        dto.ErrorMsg += Msg + "<br/>";
                        dto.ErrorCount++;
                        dto.Status = false;
                    }
                    if (prop.Name == "DataSource" && Level != FieldImportLevel.Success)
                    {
                        prop.SetValue(dto, "手动导入");
                    }
                }
                dtos.Add(dto);
            }
            return dtos;
        }

        /// <summary>
        /// 验证字段
        /// </summary>
        /// <param name="name"></param>
        /// <param name="item"></param>
        /// <param name="constructor"></param>
        /// <param name="corp"></param>
        /// <param name="project"></param>
        /// <returns></returns>
        public (FieldImportLevel Level, string Msg) VerifyProjectField(string name, ProjectImportForm item, CorpInfo? corp, ConstructorInfo? constructor, ProjectInfo? project, IEnumerable<SysArea> allarea)
        {
            //项目来源
            if (name == "DataSource")
            {
                if (!ExistEnumName<项目数据来源>(item.DataSource))
                {
                    return (FieldImportLevel.Warning, "未匹配上项目数据来源,确认导入将修改为" + 项目数据来源.手动导入.GetDescription());
                }
            }
            //招标标段编号
            if (name == "BiddingSectionNum")
            {
                if (string.IsNullOrEmpty(item.BiddingSectionNum))
                {
                    return (FieldImportLevel.Danger, "项目编号（招标标段编号）不能为空");
                }
                if (project != null)
                {
                    return (FieldImportLevel.Danger, "项目编号（招标标段编号）已存在");
                }
            }
            //项目名称
            if (name == "Name")
            {
                if (string.IsNullOrEmpty(item.Name))
                {
                    return (FieldImportLevel.Danger, "项目名称不能为空");
                }
            };
            //中标单位
            if (name == "LumpContractorCorpName")
            {
                if (string.IsNullOrEmpty(item.LumpContractorCorpName))
                {
                    return (FieldImportLevel.Danger, "中标单位不能为空");
                }
                if (corp != null)
                {
                    if (corp.Name != item.LumpContractorCorpName)
                    {
                        return (FieldImportLevel.Warning, "名称不一致，导入将采用匹配的单位名称【" + corp.Name + "】");
                    }
                }
                else
                {
                    return (FieldImportLevel.Primary, "未匹配上中标单位，导入将新增");
                }
            };
            //中标单位信用代码
            if (name == "LumpContractorCorpCode")
            {
                if (string.IsNullOrEmpty(item.LumpContractorCorpCode))
                {
                    return (FieldImportLevel.Danger, "中标单位信用代码不能为空");
                }
                if (corp == null)
                {
                    return (FieldImportLevel.Primary, "未匹配上中标单位，导入将新增");
                }
            };
            //建设单位
            if (name == "BuildCorpName")
            {
                if (string.IsNullOrEmpty(item.BuildCorpName))
                {
                    return (FieldImportLevel.Danger, "建设单位不能为空");
                }
                if (constructor == null)
                {
                    return (FieldImportLevel.Primary, "未匹配上中标单位，导入将新增");
                }
            };
            //中标金额
            if (name == "ContractAmount")
            {
            };
            //计划开始日期
            if (name == "ContractStartDate")
            {
            };
            //计划完工日期
            if (name == "ContractEndDate")
            {
            };
            //对口部门
            if (name == "IndustryType")
            {
                if (!ExistEnumName<行业主管部门>(item.IndustryType))
                {
                    return (FieldImportLevel.Danger, "未匹配上对口部门");
                }
            };
            //所属市
            if (name == "CityName")
            {
                if (!allarea.Any(i => i.Name == item.CityName))
                {
                    return (FieldImportLevel.Warning, "未匹配上所属市，该数据不会保存");
                }
                var city = allarea.FirstOrDefault(i => i.Name == item.CityName);
                var area = allarea.FirstOrDefault(i => i.Name == item.AreaName);
                if (area?.Pid != city?.Id)
                {
                    return (FieldImportLevel.Warning, "【" + item.AreaName + "】不是【" + item.CityName + "】下的地区，该数据不会保存 ");
                }
            };
            //所属县
            if (name == "AreaName")
            {
                if (!allarea.Any(i => i.Name == item.AreaName))
                {
                    return (FieldImportLevel.Warning, "未匹配上所属县，该数据不会保存");
                }
                var city = allarea.FirstOrDefault(i => i.Name == item.CityName);
                var area = allarea.FirstOrDefault(i => i.Name == item.AreaName);
                if (area?.Pid != city?.Id)
                {
                    return (FieldImportLevel.Warning, "【" + item.AreaName + "】不是【" + item.CityName + "】下的地区，该数据不会保存 ");
                }
            };
            return (FieldImportLevel.Success, "验证通过");
        }

        /// <summary>
        /// 枚举中是否存在该枚举名
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="enumName"></param>
        /// <returns></returns>
        public bool ExistEnumName<T>(string enumName)
        {
            bool flag = false;
            foreach (int myCode in Enum.GetValues(typeof(T)))
            {
                string? strName = Enum.GetName(typeof(T), myCode);//获取名称
                if (enumName == strName)
                {
                    flag = true;
                    break;
                }
            }
            return flag;
        }

        /// <summary>
        /// 导入时验证项目基本信息并对数据进行新增处理
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public void VerifyProjectToEntity(IEnumerable<ProjectImportForm> data)
        {
            //获取可能存在的所有的项目
            var projects = projectService.GetProjectInfosByBiddingSectionNum(data.Select(i => i.BiddingSectionNum));
            //获取可能存在的所有企业
            var corps = corpService.GetCorpInfos(data.Select(i => i.LumpContractorCorpCode));
            //获取可能存在的所有建设单位
            var constructors = constructorService.GetConstructorInfosByName(data.Select(i => i.BuildCorpName));
            //获取所有的区域信息
            var allarea = areaService.GetAllAreas();
            try
            {
                applicationContext.Transaction.Begin();
                //循环导入数据,循环单个导入
                foreach (var item in data)
                {
                    var project = projects.Where(i => i.BiddingSectionNum == item.BiddingSectionNum).FirstOrDefault();
                    var corp = corps.Where(i => i.Code == item.LumpContractorCorpCode).FirstOrDefault();
                    var constructor = constructors.Where(i => i.Name == item.BuildCorpName).FirstOrDefault();
                    //若项目已存在，抛出异常，此次导入数据全部回滚
                    if (project != null) throw new BusinessException("项目编号为【" + project.BiddingSectionNum + "】的项目已存在无法导入");

                    //初始化项目的基础数据
                    project = new ProjectInfo();
                    var city = allarea.FirstOrDefault(i => i.Name == item.CityName);
                    var area = allarea.FirstOrDefault(i => i.Name == item.AreaName);
                    if (area != null && city != null && area.Pid == city.Id)
                    {
                        project.AreaCode = area.Id;
                        project.CityCode = city.Id;
                    }
                    project.BiddingSectionNum = item.BiddingSectionNum;
                    project.ContractAmount = item.ContractAmount;
                    project.ContractStartDate = item.ContractStartDate ?? DateTime.Now;
                    project.ContractEndDate = item.ContractEndDate;
                    project.CreateTime = DateTime.Now;
                    project.DataSource = ExistEnumName<项目数据来源>(item.DataSource) ? Enum.Parse<项目数据来源>(item.DataSource) : 项目数据来源.手动导入;
                    if (!ExistEnumName<行业主管部门>(item.IndustryType)) throw new BusinessException("对口部门【" + item.IndustryType + "】无法正确匹配,无法导入");
                    project.IndustryType = Enum.Parse<行业主管部门>(item.IndustryType);
                    project.IsDeleted = false;
                    project.IsRegister = false;
                    project.Name = item.Name;
                    project.NeedCompletData = false;
                    project.AuditStatus = 项目审核状态.待审核;
                    project.PrjStatus = 项目状态.在建;
                    if (project.AreaCode > 0)
                    {
                        var numSerialNum = projectService.GetProjectNumAndSerialNumber(project.AreaCode);
                        project.PrjNum = numSerialNum.ProjectNum;
                        project.SerialNumber = numSerialNum.SerialNumber;
                    }

                    #region 关联施工总承包

                    if (corp != null)
                    {
                        project.LumpContractorCorpId = corp.CorpId;
                    }
                    else
                    {
                        //创建总包企业
                        corp = new()
                        {
                            DataSource = DataSource.平台导入,
                            Code = item.LumpContractorCorpCode,
                            Name = item.LumpContractorCorpName,
                            CreateTime = DateTime.Now,
                            HasAuth = false,
                            Type = ConstructorType.企业,
                        };
                        corp = corpService.CreateCorpInfoNoTransaction(corp);
                        project.LumpContractorCorpId = corp.CorpId;
                    }

                    #endregion 关联施工总承包

                    #region 关联建设单位

                    if (constructor != null)
                    {
                        project.BuildCorpId = constructor.ConstructorId;
                        project.BuildCorpCode = constructor.Code;
                        project.BuildCorpName = constructor.Name;
                    }
                    else
                    {
                        //创建建设单位
                        constructor = new()
                        {
                            Name = item.BuildCorpName,
                            CreateTime = DateTime.Now,
                            HasAuth = false,
                            Type = ConstructorType.企业,
                        };
                        constructor = constructorService.CreateConstructorNoTransaction(constructor);
                        project.BuildCorpId = constructor.ConstructorId;
                        project.BuildCorpName = constructor.Name;
                    }

                    #endregion 关联建设单位

                    //创建项目
                    project = projectService.CreateProjectInfoNoTransaction(project);

                    //设置默认项目
                    corpService.UpdateDefaultProjectId(corp, project.ProjectId);
                    constructorService.UpdateDefaultProjectId(constructor, project.ProjectId);
                    //创建管理组

                    #region 创建管理组

                    //创建总包管理组
                    applicationContext.GetService<ProjectGroupService>().CreateProjectGroup(new ProjectGroup()
                    {
                        ProjectId = project.ProjectId,
                        CorpId = project.LumpContractorCorpId,
                        Name = "项目部班组",
                        CreateTime = DateTime.Now,
                        StartDate = project.ContractStartDate,
                        EndDate = project.ContractEndDate,
                        IsManagerGroup = true
                    });

                    #endregion 创建管理组
                }
                applicationContext.Transaction.Complete();
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();
                logger.LogError(ex, ex.Message, ex.StackTrace);
                throw new BusinessException("导入项目基本信息失败");
            }
        }
    }
}